function MarkerClusterer(map, opt_markers, opt_options){ this.extend(MarkerClusterer, google.maps.OverlayView); this.map_=map; this.markers_=[]; this.clusters_=[]; this.sizes=[53, 56, 66, 78, 90]; this.styles_=[]; this.ready_=false; var options=opt_options||{}; this.gridSize_=options['gridSize']||60; this.minClusterSize_=options['minimumClusterSize']||2; this.maxZoom_=options['maxZoom']||null; this.styles_=options['styles']||[]; this.imagePath_=options['imagePath'] || this.MARKER_CLUSTER_IMAGE_PATH_; this.imageExtension_=options['imageExtension'] || this.MARKER_CLUSTER_IMAGE_EXTENSION_; this.zoomOnClick_=true; if(options['zoomOnClick']!=undefined){ this.zoomOnClick_=options['zoomOnClick']; } this.averageCenter_=false; if(options['averageCenter']!=undefined){ this.averageCenter_=options['averageCenter']; } this.setupStyles_(); this.setMap(map); this.prevZoom_=this.map_.getZoom(); var that=this; google.maps.event.addListener(this.map_, 'zoom_changed', function(){ var zoom=that.map_.getZoom(); if(that.prevZoom_!=zoom){ that.prevZoom_=zoom; that.resetViewport(); }}); google.maps.event.addListener(this.map_, 'idle', function(){ that.redraw(); }); if(opt_markers&&opt_markers.length){ this.addMarkers(opt_markers, false); }} MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_PATH_ = 'https://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclusterer/' + 'images/m'; MarkerClusterer.prototype.MARKER_CLUSTER_IMAGE_EXTENSION_='png'; MarkerClusterer.prototype.extend=function(obj1, obj2){ return (function(object){ for (var property in object.prototype){ this.prototype[property]=object.prototype[property]; } return this; }).apply(obj1, [obj2]); }; MarkerClusterer.prototype.onAdd=function(){ this.setReady_(true); }; MarkerClusterer.prototype.draw=function(){}; MarkerClusterer.prototype.setupStyles_=function(){ if(this.styles_.length){ return; } for (var i=0, size; size=this.sizes[i]; i++){ this.styles_.push({ url: this.imagePath_ + (i + 1) + '.' + this.imageExtension_, height: size, width: size }); }}; MarkerClusterer.prototype.fitMapToMarkers=function(){ var markers=this.getMarkers(); var bounds=new google.maps.LatLngBounds(); for (var i=0, marker; marker=markers[i]; i++){ bounds.extend(marker.getPosition()); } this.map_.fitBounds(bounds); }; MarkerClusterer.prototype.setStyles=function(styles){ this.styles_=styles; }; MarkerClusterer.prototype.getStyles=function(){ return this.styles_; }; MarkerClusterer.prototype.isZoomOnClick=function(){ return this.zoomOnClick_; }; MarkerClusterer.prototype.isAverageCenter=function(){ return this.averageCenter_; }; MarkerClusterer.prototype.getMarkers=function(){ return this.markers_; }; MarkerClusterer.prototype.getTotalMarkers=function(){ return this.markers_.length; }; MarkerClusterer.prototype.setMaxZoom=function(maxZoom){ this.maxZoom_=maxZoom; }; MarkerClusterer.prototype.getMaxZoom=function(){ return this.maxZoom_; }; MarkerClusterer.prototype.calculator_=function(markers, numStyles){ var index=0; var count=markers.length; var dv=count; while (dv!==0){ dv=parseInt(dv / 10, 10); index++; } index=Math.min(index, numStyles); return { text: count, index: index };}; /** * Set the calculator function. * * @param {function(Array, number)} calculator The function to set as the * calculator. The function should return a object properties: * 'text' (string) and 'index' (number). * */ MarkerClusterer.prototype.setCalculator=function(calculator){ this.calculator_=calculator; }; /** * Get the calculator function. * * @return {function(Array, number)} the calculator function. */ MarkerClusterer.prototype.getCalculator=function(){ return this.calculator_; }; MarkerClusterer.prototype.addMarkers=function(markers, opt_nodraw){ for (var i=0, marker; marker=markers[i]; i++){ this.pushMarkerTo_(marker); } if(!opt_nodraw){ this.redraw(); }}; MarkerClusterer.prototype.pushMarkerTo_=function(marker){ marker.isAdded=false; if(marker['draggable']){ var that=this; google.maps.event.addListener(marker, 'dragend', function(){ marker.isAdded=false; that.repaint(); }); } this.markers_.push(marker); }; MarkerClusterer.prototype.addMarker=function(marker, opt_nodraw){ this.pushMarkerTo_(marker); if(!opt_nodraw){ this.redraw(); }}; MarkerClusterer.prototype.removeMarker_=function(marker){ var index=-1; if(this.markers_.indexOf){ index=this.markers_.indexOf(marker); }else{ for (var i=0, m; m=this.markers_[i]; i++){ if(m==marker){ index=i; break; }} } if(index==-1){ return false; } marker.setMap(null); this.markers_.splice(index, 1); return true; }; MarkerClusterer.prototype.removeMarker=function(marker, opt_nodraw){ var removed=this.removeMarker_(marker); if(!opt_nodraw&&removed){ this.resetViewport(); this.redraw(); return true; }else{ return false; }}; MarkerClusterer.prototype.removeMarkers=function(markers, opt_nodraw){ var removed=false; for (var i=0, marker; marker=markers[i]; i++){ var r=this.removeMarker_(marker); removed=removed||r; } if(!opt_nodraw&&removed){ this.resetViewport(); this.redraw(); return true; }}; MarkerClusterer.prototype.setReady_=function(ready){ if(!this.ready_){ this.ready_=ready; this.createClusters_(); }}; MarkerClusterer.prototype.getTotalClusters=function(){ return this.clusters_.length; }; MarkerClusterer.prototype.getMap=function(){ return this.map_; }; MarkerClusterer.prototype.setMap=function(map){ this.map_=map; }; MarkerClusterer.prototype.getGridSize=function(){ return this.gridSize_; }; MarkerClusterer.prototype.setGridSize=function(size){ this.gridSize_=size; }; MarkerClusterer.prototype.getMinClusterSize=function(){ return this.minClusterSize_; }; MarkerClusterer.prototype.setMinClusterSize=function(size){ this.minClusterSize_=size; }; MarkerClusterer.prototype.getExtendedBounds=function(bounds){ var projection=this.getProjection(); var tr=new google.maps.LatLng(bounds.getNorthEast().lat(), bounds.getNorthEast().lng()); var bl=new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng()); var trPix=projection.fromLatLngToDivPixel(tr); trPix.x +=this.gridSize_; trPix.y -=this.gridSize_; var blPix=projection.fromLatLngToDivPixel(bl); blPix.x -=this.gridSize_; blPix.y +=this.gridSize_; var ne=projection.fromDivPixelToLatLng(trPix); var sw=projection.fromDivPixelToLatLng(blPix); bounds.extend(ne); bounds.extend(sw); return bounds; }; MarkerClusterer.prototype.isMarkerInBounds_=function(marker, bounds){ return bounds.contains(marker.getPosition()); }; MarkerClusterer.prototype.clearMarkers=function(){ this.resetViewport(true); this.markers_=[]; }; MarkerClusterer.prototype.resetViewport=function(opt_hide){ for (var i=0, cluster; cluster=this.clusters_[i]; i++){ cluster.remove(); } for (var i=0, marker; marker=this.markers_[i]; i++){ marker.isAdded=false; if(opt_hide){ marker.setMap(null); }} this.clusters_=[]; }; MarkerClusterer.prototype.repaint=function(){ var oldClusters=this.clusters_.slice(); this.clusters_.length=0; this.resetViewport(); this.redraw(); window.setTimeout(function(){ for (var i=0, cluster; cluster=oldClusters[i]; i++){ cluster.remove(); }}, 0); }; MarkerClusterer.prototype.redraw=function(){ this.createClusters_(); }; MarkerClusterer.prototype.distanceBetweenPoints_=function(p1, p2){ if(!p1||!p2){ return 0; } var R=6371; var dLat=(p2.lat() - p1.lat()) * Math.PI / 180; var dLon=(p2.lng() - p1.lng()) * Math.PI / 180; var a=Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); var c=2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d=R * c; return d; }; MarkerClusterer.prototype.addToClosestCluster_=function(marker){ var distance=40000; var clusterToAddTo=null; var pos=marker.getPosition(); for (var i=0, cluster; cluster=this.clusters_[i]; i++){ var center=cluster.getCenter(); if(center){ var d=this.distanceBetweenPoints_(center, marker.getPosition()); if(d < distance){ distance=d; clusterToAddTo=cluster; }} } if(clusterToAddTo&&clusterToAddTo.isMarkerInClusterBounds(marker)){ clusterToAddTo.addMarker(marker); }else{ var cluster=new Cluster(this); cluster.addMarker(marker); this.clusters_.push(cluster); }}; MarkerClusterer.prototype.createClusters_=function(){ if(!this.ready_){ return; } var mapBounds=new google.maps.LatLngBounds(this.map_.getBounds().getSouthWest(), this.map_.getBounds().getNorthEast()); var bounds=this.getExtendedBounds(mapBounds); for (var i=0, marker; marker=this.markers_[i]; i++){ if(!marker.isAdded&&this.isMarkerInBounds_(marker, bounds)){ this.addToClosestCluster_(marker); }} }; function Cluster(markerClusterer){ this.markerClusterer_=markerClusterer; this.map_=markerClusterer.getMap(); this.gridSize_=markerClusterer.getGridSize(); this.minClusterSize_=markerClusterer.getMinClusterSize(); this.averageCenter_=markerClusterer.isAverageCenter(); this.center_=null; this.markers_=[]; this.bounds_=null; this.clusterIcon_=new ClusterIcon(this, markerClusterer.getStyles(), markerClusterer.getGridSize()); } Cluster.prototype.isMarkerAlreadyAdded=function(marker){ if(this.markers_.indexOf){ return this.markers_.indexOf(marker)!=-1; }else{ for (var i=0, m; m=this.markers_[i]; i++){ if(m==marker){ return true; }} } return false; }; Cluster.prototype.addMarker=function(marker){ if(this.isMarkerAlreadyAdded(marker)){ return false; } if(!this.center_){ this.center_=marker.getPosition(); this.calculateBounds_(); }else{ if(this.averageCenter_){ var l=this.markers_.length + 1; var lat=(this.center_.lat() * (l-1) + marker.getPosition().lat()) / l; var lng=(this.center_.lng() * (l-1) + marker.getPosition().lng()) / l; this.center_=new google.maps.LatLng(lat, lng); this.calculateBounds_(); }} marker.isAdded=true; this.markers_.push(marker); var len=this.markers_.length; if(len < this.minClusterSize_&&marker.getMap()!=this.map_){ marker.setMap(this.map_); } if(len==this.minClusterSize_){ for (var i=0; i < len; i++){ this.markers_[i].setMap(null); }} if(len >=this.minClusterSize_){ marker.setMap(null); } this.updateIcon(); return true; }; Cluster.prototype.getMarkerClusterer=function(){ return this.markerClusterer_; }; Cluster.prototype.getBounds=function(){ var bounds=new google.maps.LatLngBounds(this.center_, this.center_); var markers=this.getMarkers(); for (var i=0, marker; marker=markers[i]; i++){ bounds.extend(marker.getPosition()); } return bounds; }; Cluster.prototype.remove=function(){ this.clusterIcon_.remove(); this.markers_.length=0; delete this.markers_; }; Cluster.prototype.getSize=function(){ return this.markers_.length; }; Cluster.prototype.getMarkers=function(){ return this.markers_; }; Cluster.prototype.getCenter=function(){ return this.center_; }; Cluster.prototype.calculateBounds_=function(){ var bounds=new google.maps.LatLngBounds(this.center_, this.center_); this.bounds_=this.markerClusterer_.getExtendedBounds(bounds); }; Cluster.prototype.isMarkerInClusterBounds=function(marker){ return this.bounds_.contains(marker.getPosition()); }; Cluster.prototype.getMap=function(){ return this.map_; }; Cluster.prototype.updateIcon=function(){ var zoom=this.map_.getZoom(); var mz=this.markerClusterer_.getMaxZoom(); if(mz&&zoom > mz){ for (var i=0, marker; marker=this.markers_[i]; i++){ marker.setMap(this.map_); } return; } if(this.markers_.length < this.minClusterSize_){ this.clusterIcon_.hide(); return; } var numStyles=this.markerClusterer_.getStyles().length; var sums=this.markerClusterer_.getCalculator()(this.markers_, numStyles); this.clusterIcon_.setCenter(this.center_); this.clusterIcon_.setSums(sums); this.clusterIcon_.show(); }; function ClusterIcon(cluster, styles, opt_padding){ cluster.getMarkerClusterer().extend(ClusterIcon, google.maps.OverlayView); this.styles_=styles; this.padding_=opt_padding||0; this.cluster_=cluster; this.center_=null; this.map_=cluster.getMap(); this.div_=null; this.sums_=null; this.visible_=false; this.setMap(this.map_); } ClusterIcon.prototype.triggerClusterClick=function(event){ var markerClusterer=this.cluster_.getMarkerClusterer(); google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_, event); if(markerClusterer.isZoomOnClick()){ this.map_.fitBounds(this.cluster_.getBounds()); }}; ClusterIcon.prototype.onAdd=function(){ this.div_=document.createElement('DIV'); if(this.visible_){ var pos=this.getPosFromLatLng_(this.center_); this.div_.style.cssText=this.createCss(pos); this.div_.innerHTML=this.sums_.text; } var panes=this.getPanes(); panes.overlayMouseTarget.appendChild(this.div_); var that=this; google.maps.event.addDomListener(this.div_, 'click', function(event){ that.triggerClusterClick(event); }); }; ClusterIcon.prototype.getPosFromLatLng_=function(latlng){ var pos=this.getProjection().fromLatLngToDivPixel(latlng); if(typeof this.iconAnchor_==='object'&&this.iconAnchor_.length===2){ pos.x -=this.iconAnchor_[0]; pos.y -=this.iconAnchor_[1]; }else{ pos.x -=parseInt(this.width_ / 2, 10); pos.y -=parseInt(this.height_ / 2, 10); } return pos; }; ClusterIcon.prototype.draw=function(){ if(this.visible_){ var pos=this.getPosFromLatLng_(this.center_); this.div_.style.top=pos.y + 'px'; this.div_.style.left=pos.x + 'px'; }}; ClusterIcon.prototype.hide=function(){ if(this.div_){ this.div_.style.display='none'; } this.visible_=false; }; ClusterIcon.prototype.show=function(){ if(this.div_){ var pos=this.getPosFromLatLng_(this.center_); this.div_.style.cssText=this.createCss(pos); this.div_.style.display=''; } this.visible_=true; }; ClusterIcon.prototype.remove=function(){ this.setMap(null); }; ClusterIcon.prototype.onRemove=function(){ if(this.div_&&this.div_.parentNode){ this.hide(); this.div_.parentNode.removeChild(this.div_); this.div_=null; }}; ClusterIcon.prototype.setSums=function(sums){ this.sums_=sums; this.text_=sums.text; this.index_=sums.index; if(this.div_){ this.div_.innerHTML=sums.text; } this.useStyle(); }; ClusterIcon.prototype.useStyle=function(){ var index=Math.max(0, this.sums_.index - 1); index=Math.min(this.styles_.length - 1, index); var style=this.styles_[index]; this.url_=style['url']; this.height_=style['height']; this.width_=style['width']; this.textColor_=style['textColor']; this.anchor_=style['anchor']; this.textSize_=style['textSize']; this.backgroundPosition_=style['backgroundPosition']; this.iconAnchor_=style['iconAnchor']; }; ClusterIcon.prototype.setCenter=function(center){ this.center_=center; }; ClusterIcon.prototype.createCss=function(pos){ var style=[]; style.push('background-image:url(' + this.url_ + ');'); var backgroundPosition=this.backgroundPosition_ ? this.backgroundPosition_:'0 0'; style.push('background-position:' + backgroundPosition + ';'); if(typeof this.anchor_==='object'){ if(typeof this.anchor_[0]==='number'&&this.anchor_[0] > 0 && this.anchor_[0] < this.height_){ style.push('height:' + (this.height_ - this.anchor_[0]) + 'px; padding-top:' + this.anchor_[0] + 'px;'); }else if(typeof this.anchor_[0]==='number'&&this.anchor_[0] < 0 && -this.anchor_[0] < this.height_){ style.push('height:' + this.height_ + 'px; line-height:' + (this.height_ + this.anchor_[0]) + 'px;'); }else{ style.push('height:' + this.height_ + 'px; line-height:' + this.height_ + 'px;'); } if(typeof this.anchor_[1]==='number'&&this.anchor_[1] > 0 && this.anchor_[1] < this.width_){ style.push('width:' + (this.width_ - this.anchor_[1]) + 'px; padding-left:' + this.anchor_[1] + 'px;'); }else{ style.push('width:' + this.width_ + 'px; text-align:center;'); }}else{ style.push('height:' + this.height_ + 'px; line-height:' + this.height_ + 'px; width:' + this.width_ + 'px; text-align:center;'); } var txtColor=this.textColor_ ? this.textColor_:'black'; var txtSize=this.textSize_ ? this.textSize_:11; style.push('cursor:pointer; top:' + pos.y + 'px; left:' + pos.x + 'px; color:' + txtColor + '; position:absolute; font-size:' + txtSize + 'px; font-family:Arial,sans-serif; font-weight:bold'); return style.join(''); }; window['MarkerClusterer']=MarkerClusterer; MarkerClusterer.prototype['addMarker']=MarkerClusterer.prototype.addMarker; MarkerClusterer.prototype['addMarkers']=MarkerClusterer.prototype.addMarkers; MarkerClusterer.prototype['clearMarkers'] = MarkerClusterer.prototype.clearMarkers; MarkerClusterer.prototype['fitMapToMarkers'] = MarkerClusterer.prototype.fitMapToMarkers; MarkerClusterer.prototype['getCalculator'] = MarkerClusterer.prototype.getCalculator; MarkerClusterer.prototype['getGridSize'] = MarkerClusterer.prototype.getGridSize; MarkerClusterer.prototype['getExtendedBounds'] = MarkerClusterer.prototype.getExtendedBounds; MarkerClusterer.prototype['getMap']=MarkerClusterer.prototype.getMap; MarkerClusterer.prototype['getMarkers']=MarkerClusterer.prototype.getMarkers; MarkerClusterer.prototype['getMaxZoom']=MarkerClusterer.prototype.getMaxZoom; MarkerClusterer.prototype['getStyles']=MarkerClusterer.prototype.getStyles; MarkerClusterer.prototype['getTotalClusters'] = MarkerClusterer.prototype.getTotalClusters; MarkerClusterer.prototype['getTotalMarkers'] = MarkerClusterer.prototype.getTotalMarkers; MarkerClusterer.prototype['redraw']=MarkerClusterer.prototype.redraw; MarkerClusterer.prototype['removeMarker'] = MarkerClusterer.prototype.removeMarker; MarkerClusterer.prototype['removeMarkers'] = MarkerClusterer.prototype.removeMarkers; MarkerClusterer.prototype['resetViewport'] = MarkerClusterer.prototype.resetViewport; MarkerClusterer.prototype['repaint'] = MarkerClusterer.prototype.repaint; MarkerClusterer.prototype['setCalculator'] = MarkerClusterer.prototype.setCalculator; MarkerClusterer.prototype['setGridSize'] = MarkerClusterer.prototype.setGridSize; MarkerClusterer.prototype['setMaxZoom'] = MarkerClusterer.prototype.setMaxZoom; MarkerClusterer.prototype['onAdd']=MarkerClusterer.prototype.onAdd; MarkerClusterer.prototype['draw']=MarkerClusterer.prototype.draw; Cluster.prototype['getCenter']=Cluster.prototype.getCenter; Cluster.prototype['getSize']=Cluster.prototype.getSize; Cluster.prototype['getMarkers']=Cluster.prototype.getMarkers; ClusterIcon.prototype['onAdd']=ClusterIcon.prototype.onAdd; ClusterIcon.prototype['draw']=ClusterIcon.prototype.draw; ClusterIcon.prototype['onRemove']=ClusterIcon.prototype.onRemove; (function(){ var ref, hasProp={}.hasOwnProperty, slice=[].slice; if(((ref=this['google'])!=null ? ref['maps']:void 0)==null){ return; } this['OverlappingMarkerSpiderfier']=(function(){ var ge, gm, j, lcH, lcU, len, mt, p, ref1, twoPi, x; p=_Class.prototype; ref1=[_Class, p]; for (j=0, len=ref1.length; j < len; j++){ x=ref1[j]; x['VERSION']='0.3.3'; } gm=google.maps; ge=gm.event; mt=gm.MapTypeId; twoPi=Math.PI * 2; p['keepSpiderfied']=false; p['markersWontHide']=false; p['markersWontMove']=false; p['nearbyDistance']=20; p['circleSpiralSwitchover']=9; p['circleFootSeparation']=23; p['circleStartAngle']=twoPi / 12; p['spiralFootSeparation']=26; p['spiralLengthStart']=11; p['spiralLengthFactor']=4; p['spiderfiedZIndex']=1000; p['usualLegZIndex']=10; p['highlightedLegZIndex']=20; p['legWeight']=1.5; p['legColors']={ 'usual': {}, 'highlighted': {}}; lcU=p['legColors']['usual']; lcH=p['legColors']['highlighted']; lcU[mt.HYBRID]=lcU[mt.SATELLITE]='#fff'; lcH[mt.HYBRID]=lcH[mt.SATELLITE]='#f00'; lcU[mt.TERRAIN]=lcU[mt.ROADMAP]='#444'; lcH[mt.TERRAIN]=lcH[mt.ROADMAP]='#f00'; function _Class(map1, opts){ var e, k, l, len1, ref2, v; this.map=map1; if(opts==null){ opts={};} for (k in opts){ if(!hasProp.call(opts, k)) continue; v=opts[k]; this[k]=v; } this.projHelper=new this.constructor.ProjHelper(this.map); this.initMarkerArrays(); this.listeners={}; ref2=['click', 'zoom_changed', 'maptypeid_changed']; for (l=0, len1=ref2.length; l < len1; l++){ e=ref2[l]; ge.addListener(this.map, e, (function(_this){ return function(){ return _this['unspiderfy'](); };})(this)); }} p.initMarkerArrays=function(){ this.markers=[]; return this.markerListenerRefs=[]; }; p['addMarker']=function(marker){ var listenerRefs; if(marker['_oms']!=null){ return this; } marker['_oms']=true; listenerRefs=[ ge.addListener(marker, 'click', (function(_this){ return function(event){ return _this.spiderListener(marker, event); };})(this)) ]; if(!this['markersWontHide']){ listenerRefs.push(ge.addListener(marker, 'visible_changed', (function(_this){ return function(){ return _this.markerChangeListener(marker, false); };})(this))); } if(!this['markersWontMove']){ listenerRefs.push(ge.addListener(marker, 'position_changed', (function(_this){ return function(){ return _this.markerChangeListener(marker, true); };})(this))); } this.markerListenerRefs.push(listenerRefs); this.markers.push(marker); return this; }; p.markerChangeListener=function(marker, positionChanged){ if((marker['_omsData']!=null)&&(positionChanged||!marker.getVisible())&&!((this.spiderfying!=null)||(this.unspiderfying!=null))){ return this['unspiderfy'](positionChanged ? marker:null); }}; p['getMarkers']=function(){ return this.markers.slice(0); }; p['removeMarker']=function(marker){ var i, l, len1, listenerRef, listenerRefs; if(marker['_omsData']!=null){ this['unspiderfy'](); } i=this.arrIndexOf(this.markers, marker); if(i < 0){ return this; } listenerRefs=this.markerListenerRefs.splice(i, 1)[0]; for (l=0, len1=listenerRefs.length; l < len1; l++){ listenerRef=listenerRefs[l]; ge.removeListener(listenerRef); } delete marker['_oms']; this.markers.splice(i, 1); return this; }; p['clearMarkers']=function(){ var i, l, len1, len2, listenerRef, listenerRefs, marker, n, ref2; this['unspiderfy'](); ref2=this.markers; for (i=l = 0, len1=ref2.length; l < len1; i=++l){ marker=ref2[i]; listenerRefs=this.markerListenerRefs[i]; for (n=0, len2=listenerRefs.length; n < len2; n++){ listenerRef=listenerRefs[n]; ge.removeListener(listenerRef); } delete marker['_oms']; } this.initMarkerArrays(); return this; }; p['addListener']=function(event, func){ var base; ((base=this.listeners)[event]!=null ? base[event]:base[event]=[]).push(func); return this; }; p['removeListener']=function(event, func){ var i; i=this.arrIndexOf(this.listeners[event], func); if(!(i < 0)){ this.listeners[event].splice(i, 1); } return this; }; p['clearListeners']=function(event){ this.listeners[event]=[]; return this; }; p.trigger=function(){ var args, event, func, l, len1, ref2, ref3, results; event=arguments[0], args=2 <=arguments.length ? slice.call(arguments, 1):[]; ref3=(ref2=this.listeners[event])!=null ? ref2:[]; results=[]; for (l=0, len1=ref3.length; l < len1; l++){ func=ref3[l]; results.push(func.apply(null, args)); } return results; }; p.generatePtsCircle=function(count, centerPt){ var angle, angleStep, circumference, i, l, legLength, ref2, results; circumference=this['circleFootSeparation'] * (2 + count); legLength=circumference / twoPi; angleStep=twoPi / count; results=[]; for (i=l = 0, ref2=count; 0 <=ref2 ? l < ref2:l > ref2; i=0 <=ref2 ? ++l:--l){ angle=this['circleStartAngle'] + i * angleStep; results.push(new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))); } return results; }; p.generatePtsSpiral=function(count, centerPt){ var angle, i, l, legLength, pt, ref2, results; legLength=this['spiralLengthStart']; angle=0; results=[]; for (i=l = 0, ref2=count; 0 <=ref2 ? l < ref2:l > ref2; i=0 <=ref2 ? ++l:--l){ angle +=this['spiralFootSeparation'] / legLength + i * 0.0005; pt=new gm.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle)); legLength +=twoPi * this['spiralLengthFactor'] / angle; results.push(pt); } return results; }; p.spiderListener=function(marker, event){ var l, len1, m, mPt, markerPt, markerSpiderfied, nDist, nearbyMarkerData, nonNearbyMarkers, pxSq, ref2; markerSpiderfied=marker['_omsData']!=null; if(!(markerSpiderfied&&this['keepSpiderfied'])){ this['unspiderfy'](); } if(markerSpiderfied||this.map.getStreetView().getVisible()||this.map.getMapTypeId()==='GoogleEarthAPI'){ return this.trigger('click', marker, event); }else{ nearbyMarkerData=[]; nonNearbyMarkers=[]; nDist=this['nearbyDistance']; pxSq=nDist * nDist; markerPt=this.llToPt(marker.position); ref2=this.markers; for (l=0, len1=ref2.length; l < len1; l++){ m=ref2[l]; if(!((m.map!=null)&&m.getVisible())){ continue; } mPt=this.llToPt(m.position); if(this.ptDistanceSq(mPt, markerPt) < pxSq){ nearbyMarkerData.push({ marker: m, markerPt: mPt }); }else{ nonNearbyMarkers.push(m); }} if(nearbyMarkerData.length===1){ return this.trigger('click', marker, event); }else{ return this.spiderfy(nearbyMarkerData, nonNearbyMarkers); }} }; p['markersNearMarker']=function(marker, firstOnly){ var l, len1, m, mPt, markerPt, markers, nDist, pxSq, ref2, ref3, ref4; if(firstOnly==null){ firstOnly=false; } if(this.projHelper.getProjection()==null){ throw "Must wait for 'idle' event on map before calling markersNearMarker"; } nDist=this['nearbyDistance']; pxSq=nDist * nDist; markerPt=this.llToPt(marker.position); markers=[]; ref2=this.markers; for (l=0, len1=ref2.length; l < len1; l++){ m=ref2[l]; if(m===marker||(m.map==null)||!m.getVisible()){ continue; } mPt=this.llToPt((ref3=(ref4=m['_omsData'])!=null ? ref4.usualPosition:void 0)!=null ? ref3:m.position); if(this.ptDistanceSq(mPt, markerPt) < pxSq){ markers.push(m); if(firstOnly){ break; }} } return markers; }; p['markersNearAnyOtherMarker']=function(){ var i, i1, i2, l, len1, len2, len3, m, m1, m1Data, m2, m2Data, mData, n, nDist, pxSq, q, ref2, ref3, ref4, results; if(this.projHelper.getProjection()==null){ throw "Must wait for 'idle' event on map before calling markersNearAnyOtherMarker"; } nDist=this['nearbyDistance']; pxSq=nDist * nDist; mData=(function(){ var l, len1, ref2, ref3, ref4, results; ref2=this.markers; results=[]; for (l=0, len1=ref2.length; l < len1; l++){ m=ref2[l]; results.push({ pt: this.llToPt((ref3=(ref4=m['_omsData'])!=null ? ref4.usualPosition:void 0)!=null ? ref3:m.position), willSpiderfy: false }); } return results; }).call(this); ref2=this.markers; for (i1=l = 0, len1=ref2.length; l < len1; i1=++l){ m1=ref2[i1]; if(!((m1.map!=null)&&m1.getVisible())){ continue; } m1Data=mData[i1]; if(m1Data.willSpiderfy){ continue; } ref3=this.markers; for (i2=n = 0, len2=ref3.length; n < len2; i2=++n){ m2=ref3[i2]; if(i2===i1){ continue; } if(!((m2.map!=null)&&m2.getVisible())){ continue; } m2Data=mData[i2]; if(i2 < i1&&!m2Data.willSpiderfy){ continue; } if(this.ptDistanceSq(m1Data.pt, m2Data.pt) < pxSq){ m1Data.willSpiderfy=m2Data.willSpiderfy=true; break; }} } ref4=this.markers; results=[]; for (i=q = 0, len3=ref4.length; q < len3; i=++q){ m=ref4[i]; if(mData[i].willSpiderfy){ results.push(m); }} return results; }; p.makeHighlightListenerFuncs=function(marker){ return { highlight: (function(_this){ return function(){ return marker['_omsData'].leg.setOptions({ strokeColor: _this['legColors']['highlighted'][_this.map.mapTypeId], zIndex: _this['highlightedLegZIndex'] }); };})(this), unhighlight: (function(_this){ return function(){ return marker['_omsData'].leg.setOptions({ strokeColor: _this['legColors']['usual'][_this.map.mapTypeId], zIndex: _this['usualLegZIndex'] }); };})(this) };}; p.spiderfy=function(markerData, nonNearbyMarkers){ var bodyPt, footLl, footPt, footPts, highlightListenerFuncs, leg, marker, md, nearestMarkerDatum, numFeet, spiderfiedMarkers; this.spiderfying=true; numFeet=markerData.length; bodyPt=this.ptAverage((function(){ var l, len1, results; results=[]; for (l=0, len1=markerData.length; l < len1; l++){ md=markerData[l]; results.push(md.markerPt); } return results; })()); footPts=numFeet >=this['circleSpiralSwitchover'] ? this.generatePtsSpiral(numFeet, bodyPt).reverse():this.generatePtsCircle(numFeet, bodyPt); spiderfiedMarkers=(function(){ var l, len1, results; results=[]; for (l=0, len1=footPts.length; l < len1; l++){ footPt=footPts[l]; footLl=this.ptToLl(footPt); nearestMarkerDatum=this.minExtract(markerData, (function(_this){ return function(md){ return _this.ptDistanceSq(md.markerPt, footPt); };})(this)); marker=nearestMarkerDatum.marker; leg=new gm.Polyline({ map: this.map, path: [marker.position, footLl], strokeColor: this['legColors']['usual'][this.map.mapTypeId], strokeWeight: this['legWeight'], zIndex: this['usualLegZIndex'] }); marker['_omsData']={ usualPosition: marker.position, leg: leg }; if(this['legColors']['highlighted'][this.map.mapTypeId]!==this['legColors']['usual'][this.map.mapTypeId]){ highlightListenerFuncs=this.makeHighlightListenerFuncs(marker); marker['_omsData'].hightlightListeners={ highlight: ge.addListener(marker, 'mouseover', highlightListenerFuncs.highlight), unhighlight: ge.addListener(marker, 'mouseout', highlightListenerFuncs.unhighlight) };} marker.setPosition(footLl); marker.setZIndex(Math.round(this['spiderfiedZIndex'] + footPt.y)); results.push(marker); } return results; }).call(this); delete this.spiderfying; this.spiderfied=true; return this.trigger('spiderfy', spiderfiedMarkers, nonNearbyMarkers); }; p['unspiderfy']=function(markerNotToMove){ var l, len1, listeners, marker, nonNearbyMarkers, ref2, unspiderfiedMarkers; if(markerNotToMove==null){ markerNotToMove=null; } if(this.spiderfied==null){ return this; } this.unspiderfying=true; unspiderfiedMarkers=[]; nonNearbyMarkers=[]; ref2=this.markers; for (l=0, len1=ref2.length; l < len1; l++){ marker=ref2[l]; if(marker['_omsData']!=null){ marker['_omsData'].leg.setMap(null); if(marker!==markerNotToMove){ marker.setPosition(marker['_omsData'].usualPosition); } marker.setZIndex(null); listeners=marker['_omsData'].hightlightListeners; if(listeners!=null){ ge.removeListener(listeners.highlight); ge.removeListener(listeners.unhighlight); } delete marker['_omsData']; unspiderfiedMarkers.push(marker); }else{ nonNearbyMarkers.push(marker); }} delete this.unspiderfying; delete this.spiderfied; this.trigger('unspiderfy', unspiderfiedMarkers, nonNearbyMarkers); return this; }; p.ptDistanceSq=function(pt1, pt2){ var dx, dy; dx=pt1.x - pt2.x; dy=pt1.y - pt2.y; return dx * dx + dy * dy; }; p.ptAverage=function(pts){ var l, len1, numPts, pt, sumX, sumY; sumX=sumY=0; for (l=0, len1=pts.length; l < len1; l++){ pt=pts[l]; sumX +=pt.x; sumY +=pt.y; } numPts=pts.length; return new gm.Point(sumX / numPts, sumY / numPts); }; p.llToPt=function(ll){ return this.projHelper.getProjection().fromLatLngToDivPixel(ll); }; p.ptToLl=function(pt){ return this.projHelper.getProjection().fromDivPixelToLatLng(pt); }; p.minExtract=function(set, func){ var bestIndex, bestVal, index, item, l, len1, val; for (index=l = 0, len1=set.length; l < len1; index=++l){ item=set[index]; val=func(item); if((typeof bestIndex==="undefined"||bestIndex===null)||val < bestVal){ bestVal=val; bestIndex=index; }} return set.splice(bestIndex, 1)[0]; }; p.arrIndexOf=function(arr, obj){ var i, l, len1, o; if(arr.indexOf!=null){ return arr.indexOf(obj); } for (i=l = 0, len1=arr.length; l < len1; i=++l){ o=arr[i]; if(o===obj){ return i; }} return -1; }; _Class.ProjHelper=function(map){ return this.setMap(map); }; _Class.ProjHelper.prototype=new gm.OverlayView(); _Class.ProjHelper.prototype['draw']=function(){}; return _Class; })(); }).call(this); var mapPins=[]; var thisMap; var markersArr=[]; var infowindow_global; var markerCluster; var bounds; var schoolInfoWindow; jQuery.ajaxSetup({cache: false}); function RPxRemoteMap(markersArrOfObjs){ $=jQuery; this.MapMarkers=function (markersArrOfObjs, mapPolygon){ var count=0; var lats=0; var lngs=0; var rawMarkers=[]; var infowindow; bounds=new google.maps.LatLngBounds(); $.each(markersArrOfObjs, function (i, v){ count++; if(v.lat==0||v.lat==200||v.lng==0||v.lng==200||v.lat==null||v.lng==null) return; lats=lats + v.lat; lngs=lngs + v.lng; var xyz=new google.maps.LatLng(parseFloat(v.lat), parseFloat(v.lng)); bounds.extend(xyz); rawMarkers.push({url: v.link, lat: v.lat, lng: v.lng, lid: v.lid, img: v.img}); }) var mapSettings; if(!rawMarkers.length&&typeof (mapPolygon)!='undefined'&&mapPolygon.length){ mapSettings={ center: mapPolygon[0], zoom: 9 }}else{ mapSettings={ center: {lat: lats / count, lng: lngs / count}, zoom: 9 }} if(!thisMap){ this.map=new google.maps.Map(document.getElementById('remote-map'), mapSettings); thisMap=this.map; } if($('#remote-map').attr('data-scrollwheel')=='false'){ alert($('#remote-map').attr('data-scrollwheel')); thisMap.setOptions({scrollwheel: false}); } var oms=new OverlappingMarkerSpiderfier(thisMap); if($('#remote-map').attr('data-showPolygon')!=undefined){ var showPolygon=$('#remote-map').attr('data-showPolygon'); if(typeof mapPolygon=='undefined') var mapPolygon=[]; if(typeof scParams!='undefined'){ var lparam=JSON.parse(scParams); if(typeof lparam['polygon']!='undefined'){ var mapPoly=lparam['polygon'].split('|'); $.each(mapPoly, function (i, v){ var rawpoint=v.split(':'); var point={lat: parseFloat(rawpoint[0]), lng: parseFloat(rawpoint[1])}; mapPolygon.push(point); }) }} if(showPolygon==='true'&&typeof mapPolygon!='undefined'){ $.each(mapPolygon, function (i, v){ if(v==0||v==200) return; bounds.extend(v); }); var styles; if($('#remote-map').data('polygon-style')!=undefined){ var style=$('#remote-map').data('polygon-style'); styles=style.split('|'); }else{ styles=[]; styles[0]='black'; styles[1]=0.8; styles[2]=2; styles[3]=0; styles[4]=0; } var poly=new google.maps.Polygon({ paths: mapPolygon, strokeColor: styles[0], strokeOpacity: styles[1], strokeWeight: styles[2], fillColor: styles[3], fillOpacity: styles[4] }) poly.setMap(thisMap); }} if(typeof scParams!='undefined'){ var prm=JSON.parse(scParams); if(typeof prm['zoom']!='undefined'){ var mapZoom=null; google.maps.event.addListenerOnce(thisMap, 'bounds_changed', function (){ if(mapZoom!=thisMap.getZoom()){ mapZoom=(thisMap.getZoom() + parseInt(prm['zoom'])); thisMap.setZoom(mapZoom); }}); }} thisMap.fitBounds(bounds); var thatmap=this.map; $.each(rawMarkers, function (i, v){ var markerIcon={}; markerIcon.url=WPR.MapSearch.markerUrl + 'default_' + v.img + '.png'; var marker=new google.maps.Marker({ position: {lat: parseFloat(v.lat), lng: parseFloat(v.lng)}, map: thatmap, url: v.url, lid: v.lid, iwindow: $('#infowindow_' + v.lid).html(), icon: markerIcon }); mapPins[v.lid]=marker; markersArr.push(marker); oms.addMarker(marker); marker.addListener('mouseover', function (){ if($('#remote-map').attr('data-onMarkerClick')!=undefined){ var onMarkerClick=$('#remote-map').attr('data-onMarkerClick'); if(typeof infowindowTemplate=='undefined'){ if(infowindow_global) infowindow_global.close(); var test=marker.iwindow; $('#infowindow_' + marker.lid).find('img').attr('src', $('#infowindow_' + marker.lid).find('img').data('img')); infowindow_global=new google.maps.InfoWindow({ content: $('#infowindow_' + marker.lid).html() }); infowindow_global.open(thatmap, marker); }else{ if(onMarkerClick==='infowindow'){ $.getJSON(WPR.ajaxurl, { controller: 'MapSearch', action: 'GetInfoWindow', listingid: marker.lid, template: infowindowTemplate }, function (data){ if(infowindow_global) infowindow_global.close(); infowindow_global=new google.maps.InfoWindow({ content: data.objectContents }); schoolInfoWindow.close(); infowindow_global.open(thatmap, marker); }) }else{ window.location.href=this.url; }} }else{ alert('Not exist'); }}); }); var iw=new google.maps.InfoWindow(); oms.addListener('mouseover', function (marker, event){ iw.setContent($('#infowindow_' + marker.lid).html()); $.getJSON(WPR.ajaxurl, { controller: 'MapSearch', action: 'GetInfoWindow', listingid: marker.lid, template: infowindowTemplate }, function (data){ if(infowindow_global) infowindow_global.close(); infowindow_global=new google.maps.InfoWindow({ content: data.objectContents }); google.maps.event.addListener(infowindow_global, 'mouseout', function (){ infowindow_global.close(); }); infowindow_global.open(thatmap, marker); }) }); if(thisMap.getZoom() <=19){ var style=[ { url: WPR.MapSearch.markerUrl + 'clusters/m1.png', height: 53, width: 52, anchor: [0, 0], textColor: '#000', textSize: 10 }, { url: WPR.MapSearch.markerUrl + 'clusters/m2.png', height: 56, width: 55, anchor: [0, 0], textColor: '#000', textSize: 10 }, { url: WPR.MapSearch.markerUrl + 'clusters/m3.png', height: 66, width: 65, anchor: [0, 0], textColor: '#000', textSize: 10 }, { url: WPR.MapSearch.markerUrl + 'clusters/m4.png', height: 78, width: 77, anchor: [0, 0], textColor: '#000', textSize: 10 }, { url: WPR.MapSearch.markerUrl + 'clusters/m5.png', height: 90, width: 89, anchor: [0, 0], textColor: '#000', textSize: 10 } ] markerCluster=new MarkerClusterer(thisMap, markersArr, {styles: style, maxZoom: 13}); } var afterListingsMapped; if(navigator.appName=='Microsoft Internet Explorer'||navigator.appName=='Netscape'){ afterListingsMapped=document.createEvent('CustomEvent'); afterListingsMapped.initCustomEvent("RPxListingsMapped", true, true, {detail: bounds}); }else{ afterListingsMapped=new CustomEvent( "RPxListingsMapped", { detail: bounds, message: bounds, bubbles: true, cancelable: true } ); } document.getElementById('remote-map').dispatchEvent(afterListingsMapped); }} var schools=[]; schoolInfoWindow=new google.maps.InfoWindow(); jQuery(document).ready(function ($){ $('body').on('RPxListingsMapped', function (e){ thisMap.addListener('zoom_changed', function (){ showSchools(bounds); return; }) if($('#remote-map').attr('data-show_schools')==undefined||$('#remote-map').attr('data-show_schools')=='0'){ return; } if($('#remote-map').attr('data-max_cluster_zoom')!=undefined){ if(thisMap.getZoom() < $('#remote-map').attr('data-max_cluster_zoom')) return; } /*var searchBounds=e.detail.detail; var service=new google.maps.places.PlacesService(thisMap); var request={bounds: searchBounds, type: "school"}; service.textSearch(request, function(results, status){ if(status==google.maps.places.PlacesServiceStatus.OK){ for (var i=0; i < results.length; i++){ var place=results[i]; var marker=new google.maps.Marker({ map: thisMap, position: place.geometry.location, icon: "https://willowdaleforsale.com/wpradmin/template/enfold/Modules/MapSearch/markers/default_School.png" }); schools.push(marker); google.maps.event.addListener(marker, 'mouseover', function(){ schoolInfoWindow.setContent('